#ifndef _XBENCH_BENCHMARK_HPP
#define _XBENCH_BENCHMARK_HPP

#include <vector>
#include <string>
#include <ostream>
#include "xbench/state.hpp"
#include "xbench/colorprint.hpp"

namespace xbench{
    class Benchmark{
    private:
        static std::vector<xbench::State> _states;
        static std::vector<size_t> _name_hash;
    public:
        Benchmark() = default;

        [[nodiscard]] static xbench::State& get_state(const std::string& name);
        static xbench::StateTable table();

        friend std::ostream& operator<<(std::ostream& os, const xbench::Benchmark& benchmark);
    };
}

// 通过获取可变参数列表的长度，执行伪宏函数重载
#define _STR(x) #x

#define XBENCH_ARGS_NUM3(state_name, func, ...) xbench::Benchmark::get_state(state_name).measure(func, __VA_ARGS__)
#define XBENCH_ARGS_NUM2(func, ...) xbench::Benchmark::get_state(_STR(func)).measure(func, __VA_ARGS__)

#define _MACRO_VAR_ARGS_IMPL_COUNT(_1,_2,_3,_4, N, ...) N
#define _MACRO_VAR_ARGS_IMPL(args)  _MACRO_VAR_ARGS_IMPL_COUNT args
#define _COUNT_MACRO_VAR_ARGS(...)  _MACRO_VAR_ARGS_IMPL((__VA_ARGS__, 4,3,2,1,0))

#define _MACRO_CHOOSE2(_macro, count)  _macro ## count
#define _MACRO_CHOOSE1(_macro, count)  _MACRO_CHOOSE2(_macro, count)
#define _MACRO_CHOOSE(_macro, count)  _MACRO_CHOOSE1(_macro, count)

#define _EXPAND(...) __VA_ARGS__

#define XBENCH(...) _EXPAND(_MACRO_CHOOSE(XBENCH_ARGS_NUM, _COUNT_MACRO_VAR_ARGS( __VA_ARGS__))( __VA_ARGS__))

#endif //_XBENCH_BENCHMARK_HPP
